4892. Замена

 

Дана последовательность натуральных чисел из n элементов. Требуется каждый элемент заменить на ближайший следующий за ним (то есть с большим индексом) элемент, который строго больше его по значению. Если большего элемента после данного нет, следует заменить данный элемент на ноль.

 

Вход. Первая строка содержит число элементов n (1 n 105). Вторая строка содержит n натуральных чисел ai (ai 109) – значения элементов последовательности.

 

Выход. Выведите искомую последовательность, разделяя соседние элементы одним пробелом.

 

Пример входа 1

Пример выхода 1

6

1 2 3 1 1 5

2 3 5 5 5 0

 

 

Пример входа 2

Пример выхода 2

5

1 2 3 4 5

2 3 4 5 0

 

 

РЕШЕНИЕ

структуры данных - set

 

Анализ алгоритма

Пусть числа входной последовательности a1, a2, …, an соответствуют высотам домов, расположенных рядом друг с другом. Например, первый тест можно изобразить следующим образом:

 

Пусть b1, b2, …, bn – результирующий массив. Тогда bi равно такому aj, что если посмотреть в торец i-го дома слева, то дом aj будет ближайшим видимым. Очевидно, что bn = 0.

 

Будем обрабатывать дома справа налево. Пусть ai – текущий рассматриваемый дом. Будем поддерживать множество s высот домов, видимых с левого торца i-го дома (включая ai). Тогда bi равно второму элементу множества s.

 

Рассмотрим, как поддерживать множество s при добавлении нового дома. Двигаемся справа налево, пусть уже был рассмотрен третий дом с высотой a3 = 1. Текущее множество равно s = {1, 2, 3, 5}. Обрабатываем второй дом с высотой a2 = 4. Очевидно, что он перекроет вид слева на все дома, не больше его высоты. Следует добавить значение a2 = 4 во множество s, после чего удалить из s все числа, меньшие a2 = 4 (можно воспользоваться методом erase для промежутка). После описанных операций множество примет вид s = {4, 5}.

 

Реализация алгоритма

Объявим множество s и итератор it на него. Входную и выходную последовательности храним в массивах in и out.

 

#define MAX 100001

set<int> s;

set<int>::iterator it;

int in[MAX], out[MAX];

 

Читаем входной массив.

 

scanf("%d",&n);

for(i = 0; i < n; i++)

  scanf("%d",&in[i]);

 

Обрабатываем дома справа налево.

 

for(i = n - 1; i >= 0; i--)

{

 

Вставляем во множество высоту текущего дома.

 

  s.insert(in[i]);

 

Ищем позицию высоты ini вставленного дома. Удаляем из множества s все высоты, меньшие ini.

 

  it = s.find(in[i]);

  s.erase(s.begin(),it);

 

Выводим второй элемент множества. Если его не существует, выводим 0.

 

  it++;

  if(it == s.end())

    out[i] = 0;

  else

    out[i] = *it;

}

 

Выводим результирующий массив.

 

for(i = 0; i < n; i++)

  printf("%d ",out[i]);

printf("\n");